/************************************
 * created by Tonk (tonk@ctonk.com) *
 ************************************/

// magiclist.cpp

/*
 * The Magiclist class is a template container for the STL std::list
 * object because I don't like the STL syntax. Initialize it like any
 * other template object. If you don't know what C++ templates are,
 * there's plenty of documentation on the web.
 *
 * Magiclist was designed because I wanted a dynamic array and didn't
 * like the syntax of the STL. Ironically, in writing this class I
 * learned the STL syntax and don't hate it anymore but it's still a
 * very useful class. I wanted it to 'feel' like a traditional c++
 * array, so it has a dereferencing operator just like a static array.
 *
 * Since Magiclist is just a container for the std::list object, the
 * fundamental processes are left to the STL. Because Magiclist is a
 * container class only, just as much overhead exists for a list of
 * size 1 as does for a list of size 7834.
 *
 * Documentation for members and methods are found in the declarations
 * and not in the definitions.
 */

#ifndef CPP_MAGICLIST
#define CPP_MAGICLIST

#include <list>

template <class T> class Magiclist {
	private:
		std::list< T > _list;

	public:
		Magiclist( void );
		Magiclist( Magiclist<T>& );
		Magiclist( int );
		~Magiclist();

		T& operator [] ( int );
		T& operator ++ ( void );
		void operator - ( T& );
		Magiclist& operator = ( Magiclist& );
		Magiclist& operator += ( Magiclist& );
		std::list< T >& GetList();

		T& Add( void );
		T& Add( T& );
		void Remove( T& );
		void Remove( int );
		int GetSize();
		T& Get( int );
		T& GetFirst();
		T& GetLast();
		void Resize( int );
		void Purge();
};

template <class T> Magiclist<T>::Magiclist( void ) {
	// Default constructor
	this->_list.resize( 0 );
	return;
}

template <class T> Magiclist<T>::Magiclist( Magiclist<T>& list ) {
	// Copy constructor
	this->_list.clear();
	this->_list.assign( list.GetList().begin(), list.GetList().end() );
}

template <class T> Magiclist<T>::Magiclist( int size ) {
	// Constructor for list with starting length of 'size'
	this->_list.resize( size );
}

template <class T> Magiclist<T>::~Magiclist( void ) {
	// Destructor
};

template <class T> T& Magiclist<T>::operator [] ( int n ) {
	// Returns the nth element of the list.
	// If n is too high/low, the first or last element will be returned.
	if ( n >= (int)this->_list.size() )
		return this->_list.back();
	if ( n < 0 )
		return this->_list.front();
	else {
		std::list< T >::iterator it = this->_list.begin();
		for ( int x=0; x < n; x++ )
			it++;
		return *it;
	}
}

template <class T> T& Magiclist<T>::operator ++ ( void ) {
	// Push a new element onto the list.
	this->_list.push_back( *(new T) );
	return this->_list.back();
}

template <class T> void Magiclist<T>::operator - ( T& t ) {
	// Removes 't' from the list.
	this->_list.remove( t );
	return;
}

template <class T> Magiclist<T>& Magiclist<T>::operator = ( Magiclist<T>& list ) {
	// Copies the contents of the given list.
	this->_list.clear();
	this->_list.assign( list.GetList().begin(), list.GetList().end() );
	return *this;
}

template <class T> Magiclist<T>& Magiclist<T>::operator += ( Magiclist<T>& list ) {
	// Appends the contents of the given list.
	for (	std::list< T >::iterator it = list.GetList().begin(); it != list.GetList().end(); it++ )
		this->_list.push_back( *it );
	return *this;
}

template <class T> std::list<T>& Magiclist<T>::GetList() {
	// Returns a reference to the internal std::list object
	return this->_list;
}

template <class T> T& Magiclist<T>::Add( void ) {
	// Adds a new element to the end of the list.
	this->_list.push_back( *(new T) );
	return this->_list.back();
}

template <class T> T& Magiclist<T>::Add( T& t ) {
	// Adds a new element to the end of the list,
	// then initializes that element to the value of
	// the given object.
	this->_list.push_back( t );
	return this->_list.back();
}

template <class T> void Magiclist<T>::Remove( int n ) {
	// Deletes the nth element from the list.
	if ( n < 0 || n > (int)this->_list.size() )
		return;

	this->_list.remove( this->operator [] ( n ) );
	return;
}

template <class T> void Magiclist<T>::Remove( T& t ) {
	// Deletes 't' from the list.
	this->_list.remove( t );
	return;
}

template <class T> int Magiclist<T>::GetSize() {
	// Returns the list size.
	return  (int)this->_list.size();
}

template <class T> void Magiclist<T>::Resize( int size ) {
	// Resizes the list.
	// The list will not be deleted and recreated. In other words:
	// If size is larger than this->GetSize(), new elements will be added.
	// If size is smaller than this->GetSize(), list will simply be truncated.
	this->_list.resize( size );
	return;
}

template <class T> void Magiclist<T>::Purge() {
	// Removes all list elements and resizes to 0.
	this->_list.clear();
	return;
}

template <class T> T& Magiclist<T>::Get( int n ) {
	// Returns the nth list element.
	return ( this->operator [] ( n ) );
}

template <class T> T& Magiclist<T>::GetFirst() {
	// Returns the first list element.
	return ( this->operator [] ( 0 ) );
}

template <class T> T& Magiclist<T>::GetLast() {
	// Returns the last list element.
	return ( this->operator [] ( this->GetSize() - 1 ) );
}

#endif // #ifndef CCP_MAGICLIST
